
var click_div;

var square_down;
var square_up;
var links = [];

var mouse_is_down = false;
var touch_is_down = false;

var modules = { 
	add: {help: "adds two or more signals together. can be used as a mixer"}, 
	cos: {help: "outputs a cosine signal when given a phasor as input"}, 
	cossegs: {help: "takes two or more pairs of values and directions, and outputs a fuction of points connected by cosine segments"},
	cpsoct: {help: "given a center frequency in Hz, and octaves away from the center as inputs, outputs a value in Hz"}, 
	delay: {help: "a delay line with any number of taps"}, 
	linsegs: {help: "takes two or more pairs of values and directions, and outputs a fuction of points connected by line segments"},
	mult: {help: "multiplies two or more signals.  can be used as a vca or ring modulator"}, 
	noise: {help: "random values on output at the sampling rate"}, 
	phasor: {help: "a moving phase value between zero and one at the input frequency in Hz. can be used with other modules to create an oscillator"}, 
	proc: {help: "a signal processor that first multiplies, then adds"}, 
	randcos: {help: "creates a smooth random signal"}, 
	randh: {help: "creates an abrupt random signal like a noise source patched to a sample and hold"},
	seq: {help: "a very versatile sequencer"}, 
	sh: {help: "sample and hold module"}, 
	shortout: {help: "output signed shorts to the system output"}, 
	stereopan: {help: "power balanced pan between two outputs"}, 
	trigger: {help: "use with a continuous signal to make the sample/hold work"}
};

var grid_space = 32;

function on_resize() {
	canvas.width = window.innerWidth;
	canvas.height = window.innerHeight;
	click_div.style.width = window.innerWidth + 'px';
	click_div.style.height = window.innerHeight + 'px';
	ctx.globalCompositeOperation = 'lighter';
	//alert("resized " + canvas.width + "x" + canvas.height);
	update_squares(false);
	show_menu("main");
}

function init() {
	click_div = document.getElementById('click_div');
	dumper = document.getElementById('dumper');
	buttons_div = document.getElementById('buttons_div');
	canvas_init();

	click_div.style.backgroundColor = "rgba(0,0,0,0)";
	click_div.addEventListener("touchstart", touch_started, false);
	click_div.addEventListener("touchmove", touch_moved, false);
	click_div.addEventListener("touchend", touch_ended, false);
	click_div.addEventListener('mousedown', on_mouse_down, false);
	click_div.addEventListener('mousemove', on_mouse_move, false);
	click_div.addEventListener('mouseup', on_mouse_up, false);
	click_div.addEventListener('mouseout', on_mouse_out, false);
	window.onresize = on_resize;
	on_resize();
}

function show_menu(n) {
	clear_buttons();
	if ("main" == n) { return show_menu_main(); }
	if ("modules" == n) { return show_modules_menu("module"); }
	if ("help" == n) { return show_modules_menu("help"); }
}

function show_help(n) {
	alert("show help for " + n + ":\n" + modules[n].help);
	show_menu("main");
}

function show_module(n) {
	alert("use module " + n);
	show_menu("main");
}

function show_menu_main() {
	clear_buttons();
	add_button("menu", "modules", "modules");
	add_button("menu", "help", "help");
}

function show_modules_menu(m) {

	var a = [ "add", "cos", "cossegs", "cpsoct", "delay", "linsegs",
		"mult", "noise", "phasor", "proc", "randcos", "randh",
		"seq", "sh", "shortout", "stereopan", "textout", "trigger"];
	var i;

	clear_buttons();
	for (i = 0; i < a.length; ++i) {
		add_button(m, a[i], a[i]);
	}

}

function connect_squares(a, b, clr) {
	var xa = (a.x + .5) * grid_space;
	var ya = (a.y + .5) * grid_space;
	var xb = (b.x + .5) * grid_space;
	var yb = (b.y + .5) * grid_space;
	draw_line({
		clr: clr,
		xa: xa, ya: ya,
		xb: xb, yb: yb,
		thick: 1
	});
}

function fill_square(s, clr) {
	var x = s.x * grid_space;
	var y = s.y * grid_space;
	var dot = {
		x: (x + grid_space / 2),
		y: (y + grid_space / 2),
		r: grid_space / 4,
		clr: clr
	}
	draw_dot(dot);
}

function find_square(x, y) {
	sx = Math.floor(x / grid_space);
	sy = Math.floor(y / grid_space);
	return {x: sx, y: sy};
}

function pressed(x, y) {
	square_down = find_square(x, y);
	square_up = find_square(x, y);
	update_squares(true);
}

function released(x, y) {
	square_up = find_square(x, y);
	remember_squares();
	update_squares(false);
}

function remember_squares() {
	links.push([square_down, square_up]);
}

function draw_links() {
	for (var i = 0; i < links.length; ++i) {
		fill_square(links[i][0], "purple");
		fill_square(links[i][1], "green");
		connect_squares(links[i][0], links[i][1], "blue");
	}
}

function update_squares(a) {
	canvas_clear();
	draw_grid();
	draw_links();
	if (! a) {return; }
	fill_square(square_down, "green");
	connect_squares(square_down, square_up, "yellow");
	fill_square(square_up, "red");
}

function dragged(x, y) {
	square_up = find_square(x, y);
	update_squares(true);
}

function on_mouse_out(e) {
	if (! mouse_is_down) {return;}
	mouse_is_down = false;
	remember_squares();
	update_squares(false);
}

function on_mouse_down(e) { 
	e.preventDefault();

	mouse_is_down = true;
	pressed(parseInt('' + e.clientX), parseInt('' + e.clientY));
	//dump_line("clicked down " + e.clientX + ":" + e.clientY);
}

function on_mouse_move(e) { 
	if (! mouse_is_down) { return; }
	e.preventDefault();

	dragged(parseInt('' + e.clientX), parseInt('' + e.clientY));
}

function on_mouse_up(e) { 
	e.preventDefault();
	if (! mouse_is_down) { return; }

	mouse_is_down = false;
	released(parseInt('' + e.clientX), parseInt('' + e.clientY));
	//dump_line("clicked up " + e.clientX + ":" + e.clientY);
}

function touch_ended(e) { 
	e.preventDefault();
	if (! touch_is_down) { return; }
	touch_is_down = false;
	var c = e.changedTouches[0];
	if (null == c) { return; }
	released(parseInt('' + c.clientX), parseInt('' + c.clientY));
	//dump_line("touch ended " + c.clientX + ":" + c.clientY);
}

function touch_moved(e) { 
	e.preventDefault();
	if (! touch_is_down) { return; }
	var c = e.changedTouches[0];
	if (null == c) { return; }
	dragged(parseInt('' + c.clientX), parseInt('' + c.clientY));
	//dump_line("touch ended " + c.clientX + ":" + c.clientY);
}

function touch_started(e) { 
	e.preventDefault();
	touch_is_down = true;
	var c = e.targetTouches[0];
	if (null == c) { return; }
	pressed(parseInt('' + c.clientX), parseInt('' + c.clientY));
	//dump_line("touch started " + c.clientX + ":" + c.clientY);
}

function draw_grid() {
	var row;
	var col;
	var rows = canvas.height / grid_space;
	var cols = canvas.width / grid_space;

	var xa;
	var ya;
	var xb;
	var yb;
	var clr = "gray";

	for (row = 0; row < rows; ++row) {
		xa = 0; xb = canvas.width;
		ya = yb = row * grid_space;
		draw_line({
			clr: clr,
			xa: xa, ya: ya,
			xb: xb, yb: yb,
			thick: 1
		});
	}
	for (col = 0; col < cols; ++col) {
		xa = xb = col * grid_space;
		ya = 0; yb = canvas.height;
		draw_line({
			clr: clr,
			xa: xa, ya: ya,
			xb: xb, yb: yb,
			thick: 1
		});
	}


}

function clear_buttons() {
	buttons_div.innerHTML = '';
}

function add_button(t, n, s) {
	buttons_div.innerHTML += '<input type="button" onclick="clicked(\'' +
		t + "','" + n + '\')" value="' + s + '"/> ';

}

function clicked(t, n) {
	clear_buttons();
	if ("menu" == t) { return show_menu(n); }
	if ("module" == t) { return show_module(n); }
	if ("help" == t) { return show_help(n); }
}

function dump_line(s) {
	dumper.innerHTML += escape_html(s) + "<br>";
}

function escape_html(i) {

	if (null == i) { return ''; }
	var s = '' + i;
	return s.split("&").join("&amp;").split("<").join("&lt;").split(">").join("&gt;").split('"').join("&quot;").split("'").join("&apos;");

}
